use std::path::{Path, PathBuf};
use std::{fs, fs::File, io::Read};

use super::my_err::MyErr;

/// 根据字符串获取文件父级目录地址
/// ```
/// let dir = get_folder("/public/attr/2023/abc.txt");
/// assert_eq!("/public/attr/2023", dir);
///
/// ```
pub fn get_folder(str: &str) -> String {
    let path = PathBuf::from(str);
    if let Some(folders) = path.parent() {
        folders.to_str().unwrap_or_default().to_string()
    } else {
        "".to_string()
    }
}

/// 根据字符串获取文件后缀名(不包含 .)
/// ```
/// let ext_name = get_ext_name("/public/attr/2023/abc.txt");
/// assert_eq!("txt", ext_name);
///
/// ```
pub fn get_ext_name(str: &str) -> String {
    let path = PathBuf::from(str);
    if let Some(ext) = path.extension() {
        ext.to_str().unwrap_or_default().to_string()
    } else {
        "".to_string()
    }
}

/// 获取文件大小
/// ```
///  
///
/// ```
pub fn get_file_size(str: &str) -> Result<u64, MyErr> {
    let metadata = fs::metadata(str)?;
    let size = metadata.len();
    Ok(size)
}

/// 读取文件字符串内容
pub fn read_file_string(file_path: &str) -> Result<String, MyErr> {
    if let Ok(mut file) = File::open(file_path) {
        let mut str_val = String::new();
        if let Ok(_) = file.read_to_string(&mut str_val) {
            Ok(str_val)
        } else {
            return Err(MyErr::Msg(format!("读取文件 {} 失败！", file_path)));
        }
    } else {
        return Err(MyErr::Msg(format!("打开文件 {} 失败！", file_path)));
    }
}

/// 读取文件二进制内容
pub fn read_file_binary(file_path: &str) -> Result<Vec<u8>, MyErr> {
    if let Ok(mut file) = File::open(file_path) {
        // 创建一个空的Vec<u8>来存储读取的数据
        let mut buf = Vec::new();
        if let Ok(_) = file.read_to_end(&mut buf) {
            Ok(buf)
        } else {
            return Err(MyErr::Msg(format!("读取文件 {} 失败！", file_path)));
        }
    } else {
        return Err(MyErr::Msg(format!("打开文件 {} 失败！", file_path)));
    }
}

/// 根据文件路径逐级创建文件夹
/// ```
/// mkdirs("/home/laobu/temp/work/abc.jpg")
#[allow(dead_code)]
pub fn mkdirs(file_path: &str) -> bool {
    // 直接将一个字符串切片包装成一个路径切片
    let path = Path::new(file_path);

    // 返回上级路径，若无上级路径则返回 `None`
    if let Some(parent) = path.parent() {
        if let Ok(_) = fs::create_dir_all(parent) {
            return true;
        }
    }

    false
}


/// 获取文件的MD5的128位二进制数组
pub fn get_file_md5_digest(file_path: &str) -> Result<Vec<u8>, MyErr> {
    if let Ok(mut file) = File::open(file_path) {
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer)?;
        
        let digest = md5::compute(&buffer);

        Ok(digest.to_vec())
    } else {
        return Err(MyErr::Msg(format!("打开文件 {} 失败！", file_path)));
    }
}